package com.atmilan.quartz.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.atmilan.quartz.utils.product.OrangeProductUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.atmilan.quartz.constant.Constants;
import com.atmilan.quartz.constant.enums.ProductTypeEnum;
import com.atmilan.quartz.constant.enums.StockAreaTempEnum;
import com.atmilan.quartz.constant.enums.SyncStatusEnum;
import com.atmilan.quartz.model.dto.crmeb.StoreProductCrmebRequest;
import com.atmilan.quartz.model.dto.orange.OrangeProductResDTO;
import com.atmilan.quartz.model.entity.crmeb.StoreProduct;
import com.atmilan.quartz.model.entity.crmeb.SystemConfig;
import com.atmilan.quartz.model.entity.orange.OrangeProduct;
import com.atmilan.quartz.model.entity.orange.OrangeProductSku;
import com.atmilan.quartz.model.entity.orange.OrangeProductSkuChannel;
import com.atmilan.quartz.service.IOrangeProductService;
import com.atmilan.quartz.service.IOrangeProductSkuChannelService;
import com.atmilan.quartz.service.IOrangeProductSkuService;
import com.atmilan.quartz.service.IOrangeSyncService;
import com.atmilan.quartz.service.IStoreProductService;
import com.atmilan.quartz.service.ISystemConfigService;
import com.atmilan.quartz.utils.source.SourceOrangeProductUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class OrangeSyncServiceImpl implements IOrangeSyncService {

    @Autowired
    ISystemConfigService systemConfigService;
    @Autowired
    IOrangeProductService orangeProductService;
    @Autowired
    IOrangeProductSkuService orangeProductSkuService;
    @Autowired
    IOrangeProductSkuChannelService orangeProductSkuChannelService;
    @Autowired
    IStoreProductService storeProductService;
    @Autowired
    SourceOrangeProductUtil sourceOrangeProductUtil;
    @Autowired
    OrangeProductUtil orangeProductUtil;

    @Override
    public Boolean syncOrangeProduct() {
        //数据清空
        orangeProductService.deleteAll();
        orangeProductSkuService.deleteAll();
        orangeProductSkuChannelService.deleteAll();

        int page = 1;
        int limit = 50;
        int pageCount = 1;
        long millis = System.currentTimeMillis();
        while (page <= pageCount) {
            try {
                OrangeProductResDTO orangeProductResDTO = orangeProductUtil.getOrangeProductList(page,limit);
                if (null == orangeProductResDTO || orangeProductResDTO.getSuccess() == 0) {
                    log.info("--------------- orange获取商品接口请求失败 ---------------");
                    continue;
                }
                pageCount = orangeProductResDTO.getData().getTotal()/limit + 1;
                if(CollectionUtils.isEmpty(orangeProductResDTO.getData().getItemList())){
                    log.info("--------------- orange获取商品接口请求结束 ---------------");
                    break;
                }
                //保存商品和sku
                saveGoods(orangeProductResDTO);
                log.info("--------------- orange远程抓取数据, 第: {} 页,  总共: {} 页, 总耗时: {} 分  ---------------", page, pageCount, (int) ((System.currentTimeMillis() - millis) / 1000 / 60));
                page++;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 商品源数据保存
     *
     * @param orangeProductResDTO
     */
    private void saveGoods(OrangeProductResDTO orangeProductResDTO) {
        List<OrangeProduct> goodList = new ArrayList<>();
        List<OrangeProductSku> skuList = new ArrayList<>();
        List<OrangeProductSkuChannel> channelList = new ArrayList<>();
        orangeProductResDTO.getData().getItemList().forEach(product->{
            product.getSkuList().forEach(sku->{
                sku.getSkuChannels().forEach(channel->{
                    OrangeProductSkuChannel orangeProductSkuChannel = new OrangeProductSkuChannel();
                    BeanUtils.copyProperties(channel,orangeProductSkuChannel);
                    orangeProductSkuChannel.setSkuId(sku.getSkuId());
                    channelList.add(orangeProductSkuChannel);
                });
                OrangeProductSku orangeProductSku = new OrangeProductSku();
                BeanUtils.copyProperties(sku,orangeProductSku,"skuValues");
                JSONArray skuValues = JSONArray.parseArray(JSON.toJSONString(null ==  sku.getSkuValues() ? new ArrayList<>(): sku.getSkuValues()));
                orangeProductSku.setSkuValues(skuValues.toJSONString());
                skuList.add(orangeProductSku);
            });
            OrangeProduct orangeProduct = new OrangeProduct();
            BeanUtils.copyProperties(product,orangeProduct,"imageList");
            JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(null == product.getImageList() ? new ArrayList<>(): product.getImageList()));
            orangeProduct.setImageList(jsonArray.toJSONString());
            goodList.add(orangeProduct);
        });
        orangeProductService.saveBatch(goodList);
        orangeProductSkuService.saveBatch(skuList);
        orangeProductSkuChannelService.saveBatch(channelList);
    }

    @Override
    public Boolean pushOrangeProduct() {
        try {
            //当次更新少于1千条, 则不更新, 并且重新拉取
            int count = orangeProductService.count();
            if(5000 > count){
                systemConfigService.update(Wrappers.<SystemConfig>lambdaUpdate()
                        .eq(SystemConfig :: getName, Constants.ORANGE_SYNC_STATUS)
                        .set(SystemConfig :: getFormId, SyncStatusEnum.PUSH)
                        .set(SystemConfig :: getUpdateTime, new Date())
                );
                log.info("--------------- Orange商品源数据, 少于规定条数, 不进行下发, 总条数为: {} ---------------", count);
                return false;
            }
            //将所有Leam商品更新状态置为未更新
            storeProductService.update(Wrappers.<StoreProduct>lambdaUpdate()
                    .eq(StoreProduct :: getIsEurope, ProductTypeEnum.ORANGE.getCode())
                    .set(StoreProduct :: getUpdateFlag, false)
            );

            //商品更新操作
            int pageNo = 1;
            int pageSize = 100;
            int maxPage = (count + pageSize - 1) / pageSize;
            log.info("--------------- 开始分页查询Orange商品源数据, 本次更新总条数为: {} ---------------", count);

            long millis = System.currentTimeMillis();
            while (pageNo <= maxPage) {
                try {
                    PageHelper.startPage(pageNo, pageSize);
                    List<OrangeProduct> orangeProducts = orangeProductService.list();
                    PageInfo<OrangeProduct> pageInfo = PageInfo.of(orangeProducts);
                    List<OrangeProduct> products = pageInfo.getList();
                    buildProduct(products);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                log.info("--------------- orange下发商品到数据库, 当前页数: {}, 总页数: {}, 耗时: {} 分 ---------------", pageNo, maxPage, (int) ((System.currentTimeMillis() - millis) / 1000 / 60));
                pageNo++;
            }
            // 图搜删除
            storeProductService.delSeachImage(ProductTypeEnum.ORANGE);
            // 下架所有未更新数据
            storeProductService.update(Wrappers.<StoreProduct>lambdaUpdate()
                    .eq(StoreProduct::getIsEurope, ProductTypeEnum.ORANGE.getCode())
                    .eq(StoreProduct::getUpdateFlag, false)
                    .eq(StoreProduct :: getIsShow, true)
                    .eq(StoreProduct :: getIsDel, false)
                    .set(StoreProduct::getIsShow, false)
                    .set(StoreProduct::getStock, 0)
                    .set(StoreProduct::getLastPushTime, new Date())
                    .set(StoreProduct::getIsTusou, false)
                    );
            // 下架所有sku库存
            storeProductService.downloadSku(ProductTypeEnum.ORANGE.getCode());
            
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 商品构建处理
     * @param products
     */
    private void buildProduct(List<OrangeProduct> products) {
        try {
            for (OrangeProduct product : products) {
                //商品下架状态
                if(Objects.equals(product.getShelfStatus(),0)){
                    log.info("--------------- 该商品: {} 下架状态, 不进行下放 ---------------",product.getItemId());
                    continue;
                }
                //商品没有图片，跳过
                List<String> imageList = JSONArray.parseArray(product.getImageList(), String.class);
                if(CollectionUtils.isEmpty(imageList)){
                    log.info("--------------- 该商品: {} 没有图片, 不进行下放 ---------------",product.getItemId());
                    continue;
                }
                List<OrangeProductSku> skus = orangeProductSkuService.list(Wrappers.<OrangeProductSku>lambdaQuery()
                        .eq(OrangeProductSku::getItemId, product.getItemId())
                        .gt(OrangeProductSku::getTotalStock, 0));
                List<OrangeProductSku> skuList = skus.stream().filter(e -> e.getSkuValues().contains("skuValue")).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(skuList)) {
                    continue;
                }
                List<OrangeProductSkuChannel> channelList = orangeProductSkuChannelService.list(Wrappers.<OrangeProductSkuChannel>lambdaQuery()
                        .in(OrangeProductSkuChannel::getSkuId, skuList.stream().map(OrangeProductSku::getSkuId).collect(Collectors.toList()))
                        .eq(OrangeProductSkuChannel::getSalesStatus, 1)
                        .gt(OrangeProductSkuChannel::getPrice, 0)
                        .gt(OrangeProductSkuChannel::getStock, 0));

                List<StockAreaTempEnum> tempEnumList = Arrays.asList(StockAreaTempEnum.values());
                Map<Integer,List<OrangeProductSkuChannel>> map = new HashMap<>();
                tempEnumList.forEach(temp->{
                    List<OrangeProductSkuChannel> cnChannelList;
                    if(StockAreaTempEnum.CN.equals(temp)){
                        cnChannelList = channelList.stream().filter(e -> e.getChannelName().contains("国内")).collect(Collectors.toList());
                    }else if(StockAreaTempEnum.HK.equals(temp)){
                        cnChannelList = channelList.stream().filter(e -> e.getChannelName().contains("香港")).collect(Collectors.toList());
                    }else {
                        cnChannelList = channelList.stream().filter(e -> e.getChannelName().contains(temp.getStockAreaName())).collect(Collectors.toList());
                    }
                    if(CollectionUtils.isNotEmpty(cnChannelList)){
                        map.put(temp.getTempId(),cnChannelList);
                    }
                });

                for(Map.Entry<Integer, List<OrangeProductSkuChannel>> entry : map.entrySet()){
                    List<OrangeProductSkuChannel> mapValue = entry.getValue();
                    //库存计算
                    int stock = mapValue.stream().mapToInt(OrangeProductSkuChannel::getStock).sum();
                    if(stock == 0){
                        continue;
                    }
                    // 构建实体
                    StoreProductCrmebRequest storeProductCrmebRequest = sourceOrangeProductUtil.buildOrangeProduct(product, skus,mapValue,entry.getKey());
                    // 数据保存
                    StoreProduct storeProduct = storeProductService.getByBarCode(storeProductCrmebRequest.getBarCode(), storeProductCrmebRequest.getSuppliersId(), storeProductCrmebRequest.getKeyword());
                    boolean crmebUpdate = true;
                    if (null != storeProduct && null != storeProduct.getLastPushTime()) {
                        long txyye = (System.currentTimeMillis() - storeProduct.getLastPushTime().getTime()) / 1000 / 60;
                        if (60 > txyye) {
                            log.info("--------------- 该商品: {} 上次orange更新时间: {} 小于一小时, 不进行更新 ---------------", storeProductCrmebRequest.getBarCode(), storeProduct.getLastPushTime());
                            crmebUpdate = false;
                            storeProductService.update(Wrappers.<StoreProduct>lambdaUpdate()
                                    .eq(StoreProduct::getId, storeProduct.getId())
                                    .set(StoreProduct::getUpdateFlag, true)
                            );
                        }
                    }
                    if (crmebUpdate) {
                        storeProductService.saveOtProduct(storeProductCrmebRequest, storeProduct, stock);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}
